﻿

namespace Mulala.Cavan.Application.MainBoundedContext.InformationModule
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Mulala.Cavan.Domain.MainBoundedContext.InformationModule;
    using Mulala.Cavan.Domain.MainBoundedContext.SearchModule;
    using Mulala.Cavan.Domain.Seedwork;
    using Spring.Context;
    using Spring.Context.Support;
    using Mulala.Cavan.Application.MainBoundedContext.SecurityModule;
    using Mulala.Cavan.Application.MainBoundedContext.MulalaModule;
    using Mulala.Cavan.Domain.MainBoundedContext.SecurityModule;
    using Mulala.Cavan.Application.MainBoundedContext.ProprietorModule;
    using Mulala.Cavan.Domain.MainBoundedContext.ProprietorModule;
    using Mulala.Cavan.Domain.MainBoundedContext.NannyModule;
    using Mulala.Cavan.Domain.MainBoundedContext.CorporationModule;
    using Mulala.Cavan.Application.MainBoundedContext.NannyModule;
    using Mulala.Cavan.Application.MainBoundedContext.CorporationModule;
    using Mulala.Cavan.Core.Extension;
    using Mulala.Cavan.Domain.MainBoundedContext.MulalaModule;

    public class NoteAppService : BaseAppService<Note, NoteSearch, INoteRepository>, INoteAppService
    {
        private IApplicationContext SpringContext = null;
        private INoteReceiverRepository NoteReceiverRepository { get; set; }
        private IUserAccountAppService UserAccountAppService { get; set; }
        private IProprietorAppService ProprietorAppService { get; set; }
        private INannyAppService NannyAppService { get; set; }
        private ICorporationAppService CorporationAppService { get; set; }

        public override BoolGenericResult<Note> Add(Note entity)
        {
            BoolGenericResult<Note> result = new BoolGenericResult<Note>();

            result = SendNote(entity);

            if (result.IsSuccess)
            {
                this.Repository.Save(result.Object);
            }

            return result;
        }

        public BoolGenericResult<Note> AddNoteReply(Note noteToReply, Note newNote)
        {
            BoolGenericResult<Note> result = new BoolGenericResult<Note>();

            result = SendNote(newNote, noteToReply);

            if (result.IsSuccess)
            {
                this.Repository.Save(result.Object);
            }

            return result;
        }

        public BoolGenericResult<NoteReceiver> UpdateNoteToChecked(Note note, int userAccountID)
        {
            BoolGenericResult<NoteReceiver> result = new BoolGenericResult<NoteReceiver>();
            NoteReceiverSearch search = NoteReceiverSearchFactory.CreateNoteReceiverSearch(note.ID, userAccountID);
            NoteReceiver noteReceiver = this.NoteReceiverRepository.GetAll(SpecificationFactory.CreateNoteReceiverSpecification(search)).FirstOrDefault();
            noteReceiver.IsNew = false;
            this.NoteReceiverRepository.Update(noteReceiver);

            result.Object = noteReceiver;

            return result;
        }

        public IList<Note> GetNotesByReceiver(int userAccountID)
        {
            NoteReceiverSearch search = NoteReceiverSearchFactory.CreateNoteReceiverSearch(userAccountID);
            IList<NoteReceiver> noteReceivers = this.NoteReceiverRepository.GetAll(SpecificationFactory.CreateNoteReceiverSpecification(search)).ToList();
            IList<Note> notes = new List<Note>();
            foreach (NoteReceiver nr in noteReceivers)
            {
                notes.Add(nr.Note);
            }

            return notes;
        }

        private BoolGenericResult<Note> SendNote(Note newNote, Note noteToReply = null)
        {
            this.SpringContext = ContextRegistry.GetContext();
            this.UserAccountAppService = this.SpringContext.GetObject(MulalaAppServiceConst.USERACCOUNTAPPSERVICE) as IUserAccountAppService;
            this.ProprietorAppService = this.SpringContext.GetObject(MulalaAppServiceConst.PROPRIETORAPPSERVICE) as IProprietorAppService;
            this.NannyAppService = this.SpringContext.GetObject(MulalaAppServiceConst.NANNYAPPSERVICE) as INannyAppService;
            this.CorporationAppService = this.SpringContext.GetObject(MulalaAppServiceConst.CORPORATIONAPPSERVICE) as ICorporationAppService;

            BoolGenericResult<Note> result = new BoolGenericResult<Note>();

            NoteReceiver noteReceiver = null;
            IList<NoteReceiver> noteReceivers = new List<NoteReceiver>();
            UserAccount receiverUserAccount = null;
            if (noteToReply.IsNotNull())
            {
                receiverUserAccount = this.UserAccountAppService.GetById(noteToReply.SenderUserAccount.ID);
            }
            else
            {
                receiverUserAccount = this.UserAccountAppService.GetById(newNote.NoteReceivers[0].ReceiverUserAccount.ID);
            }
            if ((SecurityIdentifier.Role)newNote.SenderUserAccount.Roles[0].ID == SecurityIdentifier.Role.Proprietor)
            {
                Proprietor proprietor = this.ProprietorAppService.GetById(newNote.SenderUserAccount.ID);
                noteReceiver = NoteReceiverFactory.CreateNoteReceiver(receiverUserAccount, false, true, proprietor.UserAccount.Name);
                noteReceivers.Add(noteReceiver);
                result = proprietor.SendNote(newNote.Title, newNote.Content, InformationIdentifier.NoteType.Normal, noteReceivers);
            }
            else if ((SecurityIdentifier.Role)newNote.SenderUserAccount.Roles[0].ID == SecurityIdentifier.Role.Nanny)
            {
                Nanny nanny = this.NannyAppService.GetById(newNote.SenderUserAccount.ID);
                noteReceiver = NoteReceiverFactory.CreateNoteReceiver(receiverUserAccount, false, true, nanny.UserAccount.Name);
                noteReceivers.Add(noteReceiver);
                result = nanny.SendNote(newNote.Title, newNote.Content, InformationIdentifier.NoteType.Normal, noteReceivers);
            }
            else if ((SecurityIdentifier.Role)newNote.SenderUserAccount.Roles[0].ID == SecurityIdentifier.Role.Corporation)
            {
                Corporation corporation = this.CorporationAppService.GetById(newNote.SenderUserAccount.ID);
                noteReceiver = NoteReceiverFactory.CreateNoteReceiver(receiverUserAccount, false, true, corporation.UserAccount.Name);
                noteReceivers.Add(noteReceiver);
                result = corporation.SendNote(newNote.Title, newNote.Content, InformationIdentifier.NoteType.Normal, noteReceivers);
            }

            return result;
        }

        public long GetUnReadNoteCount(NoteReceiverSearch search)
        {
            NoteReceiverSpecification specification = SpecificationFactory.CreateNoteReceiverSpecification(search);

            return this.NoteReceiverRepository.GetCount(specification);
        }
    }
}
